package enemies
{
	import org.flixel.*;
	
	import items.*;
	import treasures.*;
	import projectiles.*;
	
	/**
	 * ...
	 * @author JAC
	 */
	public class Enemy extends Unit
	{
		public var shouldDropTreasure:Boolean;
		public var randomizeSpeed:Boolean;
		
		protected var _target:Entity;
		protected var _treasuresCollected:uint;
		
		public function Enemy(i:int = 0, j:int = 0)
		{
			super(i, j);
			
			shouldDropTreasure = true;
			randomizeSpeed = true;
			
			_target = null;
			_treasuresCollected = 0;
		}
		
		public function overlapWithPlayer(p:Player):void
		{
			// Override this function
		}
		
		public function overlapWithTreasure(t:Treasure):void
		{
			// Override this function
			//_score += 200;
			_treasuresCollected += t._size;
			FlxG.play(Assets.SndCoins, Registry.soundVolume);
			t.taken();
		}
		
		public function overlapWithProjectile(p:Projectile):void
		{
			// Override this function
		}
		
		public function escapes():void
		{
			Registry.enemies.remove(this, true);
			_light.kill();
			exists = false;
			Tracker.enemiesEscaped++;
		}
		
		protected function get isIdle():Boolean
		{
			return pathSpeed == 0;
		}
		
		protected function get thereAreMoreTreasures():Boolean
		{
			return Registry.treasures.countLiving() > 0;
		}
		
		protected function goToNearestExit(avoidPlayer:Boolean = false):Boolean
		{
			if (avoidPlayer)
			{
				var i:uint;
				var exits:Array = Maze.getNearestExits(getMidpoint());
				for (i = 0; i < exits.length; i++)
				{
					if (goToPoint(exits[i], avoidPlayer))
					{
						return true;
					}
				}
				return false;
			}
			else
			{
				return goToPoint(Maze.getNearestExit(getMidpoint()), avoidPlayer);
			}
		}
		
		protected function goToNearestTreasure(avoidPlayer:Boolean = false):Boolean
		{
			if (Registry.treasures.length <= 0)
			{
				return false;
			}
			
			var i:uint;
			var j:uint;
			var treas:Array = Registry.treasures.members;
			
			for (i = 1; i < Registry.treasures.length; i++)
			{
				var thisDist:Number = FlxU.getDistance(getMidpoint(), (treas[i] as Treasure).getMidpoint());
				
				for (j = i; j > 0; j--)
				{
					
					var prevDist:Number = FlxU.getDistance(getMidpoint(), (treas[j - 1] as Treasure).getMidpoint());
					
					if (thisDist >= prevDist)
					{
						break;
					}
					
					var tempTreasure:Treasure = treas[j];
					treas[j] = treas[j - 1];
					treas[j - 1] = tempTreasure;
				}
			}
			
			for (i = 0; i < Registry.treasures.length; i++)
			{
				if (goToPoint((treas[i] as Treasure).getMidpoint(), avoidPlayer))
				{
					_target = treas[i];
					return true;
				}
			}
			return false;
		}
		
		protected function goToRandomExit(avoidPlayer:Boolean = false):Boolean
		{
			return goToPoint(Maze.getRandomExit(), avoidPlayer);
		}
		
		protected function goToRandomTreasure(avoidPlayer:Boolean = false):Boolean
		{
			var t:Treasure = Registry.treasures.getRandom() as Treasure;
			_target = t;
			return goToPoint(t.getMidpoint(), avoidPlayer);
		}
		
		protected function goToPoint(destination:FlxPoint, avoidPlayer:Boolean = false):Boolean
		{
			var newPath:FlxPath;
			if (avoidPlayer)
			{
				newPath = Maze.findPathAvoidingPlayer(getMidpoint(), destination);
			}
			else
			{
				newPath = Maze.findPath(getMidpoint(), destination);
			}
			
			if (newPath == null)
			{
				return false;
			}
			
			stopMoving();
			
			var randOffset:Number = randomizeSpeed ? FlxU.floor(FlxG.random() * 10) : 0;
			
			followPath(newPath, speed - randOffset);
			return true;
		}
		
		protected function goToTile(i:uint, j:uint, avoidPlayer:Boolean = false):Boolean
		{
			return goToPoint(Maze.getTileCenterByIndex(i, j), avoidPlayer);
		}
		
		protected function goToRandomTile(avoidPlayer:Boolean = false):Boolean
		{
			return goToPoint(Maze.getRandomPathTile(true), avoidPlayer);
		}
		
		protected function canSeePlayer(viewDistance:uint, useSight:Boolean = true):Boolean
		{
			if (useSight)
			{
				return Maze.playerIsInSight(getMidpoint(), facing, viewDistance) > 0;
			}
			else
			{
				return Maze.playerIsInSight(getMidpoint(), NONE, viewDistance) > 0;
			}
		}
		
		protected function canSeeObject(other:FlxObject, viewDistance:uint, useSight:Boolean = true):Boolean
		{
			if (useSight)
			{
				return Maze.objectIsInSight(getMidpoint(), other, facing, viewDistance) > 0;
			}
			else
			{
				return Maze.objectIsInSight(getMidpoint(), other, NONE, viewDistance) > 0;
			}
		}
		
		protected function dropTreasure():void
		{
			if (_treasuresCollected > 0)
			{
				var currentTile:FlxPoint = Maze.getTileByPoint(getMidpoint());
				var loot:Treasure = new LootBag(currentTile.x, currentTile.y);
				loot._size = _treasuresCollected;
				loot.addText("Size", "x" + loot._size, 35, 10000);
				Registry.treasures.add(loot);
				FlxG.play(Assets.SndCoins, Registry.soundVolume);
			}
		}
		
		override protected function onDeath():void
		{
			if (shouldDropTreasure)
			{
				dropTreasure();
			}
			
			Tracker.enemiesDefeated++;
			Registry.enemies.remove(this, true);
			super.onDeath();
		}
	}
}